﻿using AntMovement.Core.Entity;
using AntMovement.Core.IParameter;
using AntMovement.Core.Logic.Base;
using AntMovement.Core.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AntMovement.Core.Logic
{
    public class AirCylinder : Prism.Mvvm.BindableBase, IAirCylinder
    {
        private AirCylinderModel _airCylinder;
        #region 输入
        private NormalOpen _open;
        private NormalOpen _close;
        #endregion

        #region 输出
        private ICoil _coilOpen;
        private ICoil _coilClose;
        #endregion

        #region 字段
        private bool _isDouble = false;
        private bool _alarm_Open = false;
        private bool _alarm_Close = false;
        private Ton _tonOpen = new Ton();
        private Ton _tonClose = new Ton();

        private ILog _log;
        #endregion

        #region 属性
        private bool _reach_Open;

        public bool Reach_Open
        {
            get { return _reach_Open; }
        }

        private bool _reach_Close;

        public bool Reach_Close
        {
            get { return _reach_Close; }
        }

        public bool Auto_Open { get; set; }
        public bool Auto_Close { get; set; }
        private bool _manual_Open;

        public bool Manual_Open
        {
            get { return _manual_Open; }
            set { SetProperty(ref _manual_Open, value); }
        }

        private bool _manual_Close;

        public bool Manual_Close
        {
            get { return _manual_Close; }
            set { SetProperty(ref _manual_Close, value); }
        }

        public string Name => _airCylinder.Name;

        private bool _alarm = false;
        public bool Alarm => _alarm;

        public string In_OpenName => _airCylinder.In_OpenName;

        public string In_CloseName => _airCylinder.In_CloseName;

        public string Out_OpenName => _airCylinder.Out_OpenName;

        public string Out_CloseName => _airCylinder.Out_CloseName;
        #endregion

        public AirCylinder(ILog log, IIOParameter io, AirCylinderModel airCylinder)
        {
            _airCylinder = airCylinder;

            _open = io.GetNormalOpen(_airCylinder.In_open);
            _close = io.GetNormalOpen(_airCylinder.In_close);

            _coilOpen = io.GetCoil(_airCylinder.Open_text);
            if (!string.IsNullOrEmpty(_airCylinder.Close_text))
            {
                _isDouble = true;
                _coilClose = io.GetCoil(_airCylinder.Close_text);
            }
            if (_isDouble)
            {
                Manual_Open = _open.Execute();
                Manual_Close = _close.Execute();
            }
            else
            {
                Manual_Open = _open.Execute();
                Manual_Close = !_open.Execute();
            }

            _log = log;
        }

        public void Execute(bool auto, bool manual)
        {
            if (_isDouble)
            {
                if ((auto && Auto_Open) || (manual && Manual_Open))
                {
                    _coilClose.Execute(false);
                    _coilOpen.Execute(true);
                }
                else if ((auto && Auto_Close) || (manual && Manual_Close))
                {
                    _coilOpen.Execute(false);
                    _coilClose.Execute(true);
                }
            }
            else
            {
                if ((auto && Auto_Open) || (manual && Manual_Open))
                {
                    _coilOpen.Execute(true);
                }
                else if ((auto && Auto_Close) || (manual && Manual_Close))
                {
                    _coilOpen.Execute(false);
                }
            }
            if (auto && !manual)
            {
                Manual_Open = Auto_Open;
                Manual_Close = Auto_Close;
            }
            SetProperty(ref _reach_Close, _close.Execute(), "Reach_Close");
            SetProperty(ref _reach_Open, _open.Execute(), "Reach_Open");
            _tonOpen.Time(_airCylinder.Open_timeout, (manual && Manual_Open || auto && Auto_Open) && !_alarm_Open && !_reach_Open);
            _tonClose.Time(_airCylinder.Close_timeout, (manual && Manual_Close || auto && Auto_Close) && !_alarm_Close && !_reach_Close);
            if (_tonOpen.Out && !_alarm_Open)
            {
                _log.Error("气缸", $"[{_airCylinder.Name}] 打开超时!!!");
                _alarm_Open = true;
            }
            if (_tonClose.Out && !_alarm_Close)
            {
                _log.Error("气缸", $"[{_airCylinder.Name}] 关闭超时!!!");
                _alarm_Close = true;
            }

            SetProperty(ref _alarm, _alarm_Close || _alarm_Open, "Alarm");
        }

        public void Resetting()
        {
            _alarm_Open = false;
            _alarm_Close = false;
        }
    }
}
